import { stream } from "@kit.ArkTS";
import hilog from "@ohos.hilog";
import { BusinessError } from "@kit.BasicServicesKit";

export class PassThrough extends stream.Duplex {
  private hasDestination: boolean = false;
  private checkErrorCallback = (err:Error):void=>{}
  constructor(private streamInput: stream.Readable,private tag:string) {
    super();
    this.cork();
    this.on('drain',()=>{
      hilog.info(0,this.tag,`on drain upStream.readableEnded=${this.streamInput.readableEnded}`)
      if (this.streamInput.readableEnded) {
        this.end()
      }
    })
  }


  doWrite(chunk: string | Uint8Array, encoding: string, callback: Function): void {
    hilog.info(0,this.tag,`doWrite hasDestination=${this.hasDestination} `)
    if (chunk === undefined){
      hilog.info(0,this.tag,`doWrite chunk=undefiend`)
    }else if (typeof chunk === 'string'){
      hilog.info(0,this.tag,`doWrite string chunk=${chunk}`)
    }else{
      hilog.info(0,this.tag,`doWrite Uint8Array chunk=${chunk?.toString()}`)
    }
    if (this.hasDestination) {
      this.doPush(chunk,encoding,callback);
    } else {
      this.write(chunk,encoding,callback)
    }
  }

  doPush(chunk: string | Uint8Array, encoding: string, callback: Function){
    hilog.info(0,this.tag,' do push chunk = '+chunk.toString())
    this.push(chunk,encoding)
    callback();
  }

  doRead(size: number): void {
  }
  pipe(destination: stream.Writable): stream.Writable {
    hilog.info(0,this.tag,'pipe as upStream ')
    this.hasDestination = true;
    this.uncork();
    return super.pipe(destination);
  }

  end(chunk?: string | Uint8Array | undefined, encoding?: string | undefined, callback?: Function | undefined): stream.Writable {
    hilog.info(0,this.tag,`end writableLength=${this.writableLength} `)
    if (chunk === undefined){
      hilog.info(0,this.tag,`end chunk=undefiend`)
    }else if (typeof chunk === 'string'){
      hilog.info(0,this.tag,`end string chunk=${chunk}`)
    }else{
      hilog.info(0,this.tag,`end Uint8Array chunk=${chunk?.toString()}`)
    }
    if (this.writableLength>0){
      if (chunk) {
        this.write(chunk,encoding,callback)
      }
      return this
    }else{
      this.finally().then(()=>{
        hilog.info(0,this.tag,`end check corret`)
        super.end(chunk,encoding,callback)
      }).catch((err:Error)=>{
        hilog.error(0,this.tag,`end check error = ${err.message}`)
        this.checkErrorCallback && this.checkErrorCallback(err)
      })
      return this
    }
  }

  async finally():Promise<void>{
    return
  }

  onEndCheckError(checkErrorCallback:(err:Error)=>void){
    this.checkErrorCallback = checkErrorCallback
  }
}